﻿using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;


using MapCenterSystem.DataInfo;
using MapCenterSytem.Process;
using MapCenterSystem.ServiceProvider.GoogleMap;
using MapCenterSystem.ServiceProvider.LocalMap;
using MapCenterSystem.Utility;
using System.Drawing;
using System.Drawing.Imaging;
using MapCenterSystem.DefineType;
using System.Web.SessionState;
using System.Collections.Generic;
using System.IO;
using System.Configuration;


namespace MobiMap.Admin
{
    /// <summary>
    /// Summary description for $codebehindclassname$
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class MapHandler : IHttpHandler, IRequiresSessionState
    {
        static int TILE_SIZE = 256;
        static int MAX_WIDTH = TILE_SIZE * 2;
        static int MAX_HEIGHT = TILE_SIZE * 2;
        static int DEFAULT_WIDTH = 512;
        static int DEFAULT_HEIGHT = 512;
        static int DEFAULT_ZOOM = 15;
        static int DEFAULT_TYPE = 0;
        static int MAX_ZOOM = 20;
        static int MIN_ZOOM = 7;
        static double DEFAULT_LONG = 106.682374;
        static double DEFAULT_LAT = 10.762737;

        int screenWidth = DEFAULT_WIDTH;
        int screenHeight = DEFAULT_HEIGHT;

        PointF placeCoor;
        public void ProcessRequest(HttpContext context)
        {
            HttpResponse response = context.Response;
            HttpRequest request = context.Request;
            response.ContentType = "image/png";
            
            MapInfoEx map = null;

            if (request.QueryString["newcenter"] != null)
            {
                if (context.Session["MAP"] != null)
                    map = (MapInfoEx)context.Session["MAP"];
 
                context.Session["MAP"] = GetMapByPostion(map, request.QueryString["newcenter"]);
                context.Session["mobimap_placeCoor"] = placeCoor;
            }


            if (context.Session["MAP"] != null)
            {
                map = (MapInfoEx)context.Session["MAP"];
                //map type
                if (request.QueryString["type"] != null)
                    map.MapType = int.Parse(request.QueryString["type"]);

                //map zoom
                if (request.QueryString["zoom"] != null)
                {
                    int z = int.Parse(request.QueryString["zoom"]);
                    if (!((map.Zoom == MAX_ZOOM && z == 1) || (map.Zoom == MIN_ZOOM && z == -1)))
                    {
                        map.Zoom += z;
                    }                    
                }

                if (request.QueryString["move"] != null)
                {
                    string move = request.QueryString["move"];
                    double distance = 0.00008 * Math.Pow(2, 20 - map.Zoom);
                    if (move == "right")
                    {
                        map.CoordinateCenter.Longitude += distance;
                    }
                    else if (move == "left")
                    {
                        map.CoordinateCenter.Longitude -= distance;
                    }
                    else if (move == "up")
                    {
                        map.CoordinateCenter.Latitude += distance;
                    }
                    else if (move == "bottom")
                    {
                        map.CoordinateCenter.Latitude -= distance;
                    }
                }                
            }
            else
            {
                map = new MapInfoEx();
                map.Zoom = DEFAULT_ZOOM;
                map.Size = new Size(screenWidth, screenHeight);
                map.MapType = DEFAULT_TYPE;
                map.CoordinateCenter = new Coordinate(DEFAULT_LAT, DEFAULT_LONG); 
            }

            if (context.Application["mobimap_mapsource"] != null)
            {
                map.MapSource = (int)context.Application["mobimap_mapsource"];
            }
            else
            {
                map.MapSource = 1;//////////////////////////
            }
            map.GlobalToMap();
            //map.MapCenter.Y -= 50;
            map.Tile = new Point(map.MapCenter.X / TILE_SIZE, map.MapCenter.Y / TILE_SIZE);
            map.MapStore = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MapData");
            context.Session["MAP"] = map;
            System.Drawing.Image result;

            try
            {
                if (map.MapSource == 0)
                {
                    GoogleMapProviderEx g = new GoogleMapProviderEx();
                    result = g.GetMapImage(map);
                }
                else
                {
                    LocalMapProviderEx g = new LocalMapProviderEx();
                    result = g.GetMapImage(map);
                }    
                result.Save(context.Response.OutputStream, ImageFormat.Png);
                result.Dispose();

                if (context.Session["mobimap_placeCoor"] != null)
                {
                    Point center = new Point(map.MapCenter.X, map.MapCenter.Y);
                    Point topleft = new Point(center.X - map.Size.Width / 2,
                                                center.Y - map.Size.Height / 2);
                    PointF coor = (PointF)context.Session["mobimap_placeCoor"];
                    Point placePoint = LocateConvert.ToPoint(new Coordinate(coor.X, coor.Y), map.Zoom);
                    context.Session["mobimap_placePoint"] = (placePoint.X - topleft.X) + "@" + (placePoint.Y - topleft.Y);
                }

            }

            

            catch (Exception ex)
            {
                //map = new MapInfoEx();
                map.Zoom = DEFAULT_ZOOM;
                map.Size = new Size(screenWidth, screenHeight);
                map.MapType = DEFAULT_TYPE;                
                map.CoordinateCenter = new Coordinate(DEFAULT_LAT, DEFAULT_LONG);             
                
                map.GlobalToMap();
                map.Tile = new Point(map.MapCenter.X / TILE_SIZE, map.MapCenter.Y / TILE_SIZE);
                map.MapStore = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MapData");
                context.Session["MAP"] = map;
                if (map.MapSource == 0)
                {
                    GoogleMapProviderEx g = new GoogleMapProviderEx();
                    result = g.GetMapImage(map);
                }
                else
                {
                    LocalMapProviderEx g = new LocalMapProviderEx();
                    result = g.GetMapImage(map);
                }   
                result.Save(context.Response.OutputStream, ImageFormat.Png);
                result.Dispose();                
            }     
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        public MapInfoEx GetMapByPostion(MapInfoEx mapinfo, string newcenter)
        {
            MapInfoEx map;
            if (mapinfo == null)
            {
                map = new MapInfoEx();
                map.Zoom = DEFAULT_ZOOM;
                map.Size = new Size(screenWidth, screenHeight);
                map.MapType = DEFAULT_TYPE;
            }
            else
            {
                map = mapinfo;
            }

            string[] arrInfo = newcenter.Split('@');
            
            //Neu da gui latitude va longitude
            if (arrInfo[0] == "latlong") 
            {
                float latitude = float.Parse(arrInfo[1]);
                float longitude = float.Parse(arrInfo[2]);
                placeCoor = new PointF(latitude, longitude);
                map.CoordinateCenter = new Coordinate(latitude, longitude);
            }
            else if (arrInfo[0] == "pixel")
            {
                int newCenterX = int.Parse(arrInfo[1]);
                int newCenterY = int.Parse(arrInfo[2]);

                Point pxCenter = new Point(map.Size.Width / 2, map.Size.Height / 2);
                Point curPoint = Point.Empty;
                curPoint.X = map.MapCenter.X + (newCenterX - pxCenter.X);
                curPoint.Y = map.MapCenter.Y + (newCenterY - pxCenter.Y);

                map.CoordinateCenter = LocateConvert.ToGeographicCoordinate(curPoint, map.Zoom);
                
            }

            else if (arrInfo[0] == "address")//neu gui chuoi dia chi sang
            {
                HomeInfoEx homeinfo = new HomeInfoEx();
                string keyWordAddress = StringHelper.StandardizeString(arrInfo[1]);
                List<string> lst = StringHelper.GetNumberAndStreet(keyWordAddress);
                string area = StringHelper.GetSearchString(lst[1], AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["abbr_file"]);
                IList<HomeInfoEx> lstHome = HomeBUS.FindExactAddress(lst[0], area);
                if (lstHome.Count == 0)
                {
                    lstHome = HomeBUS.FindNearAddress(StringHelper.GetExactNumber(lst[0]), area);
                }
                if (lstHome.Count <= 0)
                    return null;

                homeinfo = lstHome[0];
                placeCoor = new PointF((float)homeinfo.Coordinate.Latitude,
                                            (float)homeinfo.Coordinate.Longitude);

                map.CoordinateCenter = new Coordinate(homeinfo.Coordinate.Latitude,
                                                        homeinfo.Coordinate.Longitude);
            }

            return map;            
        }
    }
}
